package string;
/**
 * 字符串Sting
 * 内部使用一个char数组保存所有字符，每个字符为2字节，存的是该字符Unicode编码。
 * 字符串是不变对象，
 * 一旦创建内容不可改变，
 * 若改变会创建新对象
 */
public class StringDemo {
    public static void main(String[] args) {
        /*
         字符串常量池
         java在堆内存中开辟了一段空间用于缓存所有使用字面量形式创建的字符串对象，
         并在后期再次使用该字面量创建字符串的重用对象，避免内存中堆积大量内容一样
         的字符串对象来减小内存开销
        */
        String s1 = "123abc";//字面量
        String s2 = "123abc";//与s1字面量相同，重用对象
        //地址相同，说明s2重用了s1对象
        System.out.println(s1 == s2);

        String s4 = new String("123abc");//new会产生新对象
        System.out.println("s4:"+ s4);
        System.out.println(s1 == s4);//false

        System.out.println(s1.equals(s4));//判断内容是否相同

        String s3 = "123ABc";
        System.out.println(s1.equalsIgnoreCase(s3));//忽略大小写对比内容

        s1 = s1+"!";//生成一个新的字符串对象
        System.out.println(s1 == s2);//false，不再指向同一对象

        /*
        这里触发了一个编译器的特性：
        编译器在编译期间若遇到几个计算表达式，发现在编译期可以确定结果时就会进行计算
        并将结果编译到class文件中，这样以来JVM每次执行字节码文件就无需再计算
         */
        String s5 = "123" + "abc";//代码被编译器改为String s5 = "123abc"; 因此s5在常量池中的对象，所在地址与s2相同
        System.out.println(s2 == s5);//true

        String s = "123";
        String s6 = s + "abc";
        System.out.println(s2 == s6);//false

        String s7 = 1 + 2 + 3 + "abc";//6abc;
        System.out.println(s2 == s7);//false

        String s8 = 1+'2'+3+"abc";
        System.out.println(s2 == s8);//false

        String s9 = 1+"2"+3+"abc";
        System.out.println(s2 == s9);//true



    }
}
